﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace SanGuoXiuGai
{
    public class MemoryHelper
    {
        [DllImport("kernel32.dll")]
        public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int size, out int numBytesRead);
        [DllImport("kernel32.dll")]
        public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int size, out int numBytesWrite);

        [DllImport("kernel32.dll")]
        public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

        [DllImport("kernel32.dll")]
        public static extern bool CloseHandle(IntPtr hProcess);

        private const int PROCESS_ALL_ACCESS = 0x1F0FFF;
        private const int PROCESS_VM_READ = 0x0010;
        private const int PROCESS_VM_WRITE = 0x0020;


        public Process CurrentProcess { get; set; }
        private IntPtr Handle = IntPtr.Zero;

        public MemoryHelper(string windowTitle)
        {
            Process[] arrayProcess = Process.GetProcesses(Environment.MachineName);
            foreach (Process process in arrayProcess)
            {
                if (process.MainWindowHandle != IntPtr.Zero && process.MainWindowTitle == windowTitle)
                {
                    CurrentProcess = process;
                    Handle = process.Handle;
                }
            }
        }

        /// <summary>
        /// 读取内存值
        /// </summary>
        /// <param name="size">2int16、4int32、8int64</param>
        /// <returns></returns>
        public long ReadValue(int address, byte size = 2)
        {
            if (CurrentProcess == null)
                return 0;

            int readSize;
            byte[] byData = new byte[size];
            bool flag = ReadProcessMemory(Handle, (IntPtr)address, byData, size, out readSize);

            if (readSize == 2)
                return BitConverter.ToInt16(byData, 0);
            else if (readSize == 4)
                return BitConverter.ToInt32(byData, 0);
            else if (readSize == 8)
                return BitConverter.ToInt64(byData, 0);
            else
                return 0;
        }

        public bool WriteValue(int address, byte[] value)
        {
            if (CurrentProcess == null)
                return false;

            int nReadSize;
            bool flag = WriteProcessMemory(Handle, (IntPtr)address, value, value.Length, out nReadSize);
            return flag;
        }
    }
}
